package com.benmei.weike.service;

import com.benmei.weike.common.Constants;
import com.benmei.weike.dao.*;
import com.benmei.weike.dto.*;
import com.benmei.weike.dto.IntoClassRoom.*;
import com.benmei.weike.dto.LeaveClassRoom.LeaveClassRoomRequest;
import com.benmei.weike.entity.*;
import com.benmei.weike.entity.reserve.ScheduleList;
import com.benmei.weike.entity.reserve.TdNtReserveTimeList;
import com.benmei.weike.exception.ClientException;
import com.benmei.weike.getuipush.AndroidReserveTeacher;
import com.benmei.weike.getuipush.IosReserveTeacher;
import com.benmei.weike.util.*;
import com.nativetalk.base.RetInfo;
import com.nativetalk.bean.member.TdNtMember;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;

/**
 * Created by Peter on 2017/9/6.
 */
@Service
public class AppointmentService {

    @Value("${cou.time}")
    public String cou_time;
    public static final Logger logger = LoggerFactory.getLogger(AppointmentService.class);

    @Resource
    private AppointmentDao appointmentDao;

    @Resource
    private ClassRoomDao classRoomDao;

    @Resource
    private WebsiteConfigDao websiteConfigDao;

    @Resource
    private CourseInfoDao courseInfoDao;

    @Resource
    private TeacherDao teacherDao;

    @Resource
    private StudentDao studentDao;

    @Resource
    private CoursePictureDao coursePictureDao;

    @Resource
    private ClassRoomEntryLogDao classRoomEntryLogDao;

    @Resource
    private MemberCourseDao memberCourseDao;

    @Resource
    private TdNtSystemMessageDao tdNtSystemMessageDao;

    @Resource
    private DiscountCouponDao discountCouponDao;

    @Resource
    private PaymentDao paymentDao;

    @Resource
    private SystemConfigDao systemConfigDao;

    @Resource
    private AgoraUidService agoraUidService;

//    private static Integer cou_time = 30;

    /**
     * 添加一个预约信息。学生预约老师
     *
     * @param appointment
     */
    @Transactional
    public List<ScheduleList> studentAppointTeacher(Appointment appointment, TdNtMember member, TimeZone clientTimeZone) {

        DiscountCoupon discountCoupon = new DiscountCoupon();

        //是体验课则在用户套餐表中添加一条记录
        if (appointment.getIs_trial()) {
            //查询用户可用的优惠券
            discountCoupon = discountCouponDao.selectCouponByMembId(member.getMemb_id());
            if (discountCoupon == null || discountCoupon.getDiscount_id() == 0) {
                throw new ClientException("没有可用的体验券");
            }
            Setmeal goods = paymentDao.findTsNtTrialSetmeal(appointment.getCou_id());//查询出商品信息：课程套餐
            Setmeal setmeal = new Setmeal();
            setmeal.setCou_id(goods.getCou_id());
            setmeal.setEnd_time(new Timestamp(DateUtil.getTime(goods.getSet_type(), goods.getSize())));
            setmeal.setMemb_id(member.getMemb_id());
            setmeal.setMinute_amout(goods.getSet_amout().divide(new BigDecimal(goods.getSet_time()), 2, BigDecimal.ROUND_HALF_EVEN));// 每分钟价格
            setmeal.setOriginal_price(goods.getOriginal_price());
            setmeal.setSet_amout(goods.getSet_amout());
            setmeal.setSet_id(goods.getSet_id());
            setmeal.setSet_limit(goods.getSet_limit());
            setmeal.setSet_name(goods.getSet_name());
            setmeal.setSet_synopis(goods.getSet_synopis());
            setmeal.setSet_time(goods.getSet_time());
            setmeal.setSet_type(goods.getSet_type());
            setmeal.setSurplus_time(goods.getSet_time());
            setmeal.setSet_picture(goods.getSet_picture());
            setmeal.setSize(goods.getCou_size());// 套餐课时数
            setmeal.setSet_reserve_size(goods.getCou_size());
            setmeal.setState(Constants.SetMealPayState.paid);// 支付状态
            setmeal.setMfchg_id(0);// 订单号
            setmeal.setCou_time(goods.getCou_time());// 1节课的时长
            setmeal.setDiscount_id(discountCoupon.getDiscount_id());
            paymentDao.addMembSetmeal(setmeal);
        }

        // 3. 查询该课程下学生已购买的、可预约次数>0的、最快失效的套餐（因为一门课学生可以买多次，即将过期的套餐优先预约），如
        Setmeal membSetmeal = appointmentDao.findFirstExpireSetmeal(appointment.getMemb_id(), appointment.getCou_id());

        if (membSetmeal == null) {
            throw new ClientException("课时不足");
        }
        /**
         * 判断是否是体验课，体验课查询用户可用优惠券
         */
        List<DiscountCoupon> discountCouponList = new ArrayList<>();
        if (appointment.getIs_trial()) {
            discountCouponList = discountCouponDao.searchDiscountCoupon(member.getMemb_id());
            if (discountCouponList == null) {
                throw new ClientException("该体验课没有体验券");
            }
        }
        // 查询课程对应套餐时长（该课程的已购买套餐中最早购买的）
        //预约结束时间
        Date end_time = new Date(appointment.getReserve_start_time().getTime() + membSetmeal.getCou_time() * 60 * 1000);
        appointment.setReserve_end_time(end_time);

        // 1. 根据套餐时长查询老师该时间段是否已经被预约
        Appointment appointmentForTeacher = appointmentDao.findConflictAppointmentForTeacher(appointment.getTea_id(), appointment.getReserve_start_time(), appointment.getReserve_end_time());
        if (appointmentForTeacher != null) {
            throw new ClientException("老师该时间已被预约,请预约其他时间或预约其他老师[" + appointment.getReserve_start_time() + " - " + appointment.getReserve_end_time() + "]");
        }
        // 2. 检查该学生在该时间段是否预约了其他老师
        Appointment appointmentForMember = appointmentDao.findConflictAppointmentForMember(appointment.getTea_id(), appointment.getReserve_start_time(), appointment.getReserve_end_time());
        if (appointmentForMember != null) {
            throw new ClientException("该时间段您已预约了其他老师,请预约其他时间[" + appointment.getReserve_start_time() + " - " + appointment.getReserve_end_time() + "]");
        }
        // 3. 查询老师该时间段是否为可预约状态：是否可用 0:是,1:否,2:被预约
        int reserve_course_time = (int) Math.ceil((double) membSetmeal.getCou_time() / Integer.parseInt(cou_time));
        int cou_time = 0;
        cou_time = appointmentDao.findCourseReserveTimeForTeacher(appointment.getTea_id(), appointment.getReserve_start_time(), appointment.getReserve_end_time());
        if (cou_time == 0) {
            throw new ClientException("老师没有开启预约时间[" + appointment.getReserve_start_time() + " - " + appointment.getReserve_end_time() + "]");
        } else if (cou_time < reserve_course_time) {
            throw new ClientException("老师开启的时间不足" + membSetmeal.getCou_time() + "分钟");
        }
//        ReserveTime reserveTime=  appointmentDao.findConflictReserveTimeForTeacher(appointment.getTea_id(), appointment.getReserve_start_time(), appointment.getReserve_end_time(),membSetmeal.getCou_time());
//        if (reserveTime != null) {
//            if(ReserveTime.TimeStatus.BOOKED == reserveTime.getIs_valid().intValue()){
//                throw new ClientException("老师该时间已被预约["+appointment.getReserve_start_time() +" - " +appointment.getReserve_end_time()+"]");
//            }else if(ReserveTime.TimeStatus.CLOS == reserveTime.getIs_valid().intValue()){
//                throw new ClientException("老师该时间未开启预约["+appointment.getReserve_start_time() +" - " +appointment.getReserve_end_time()+"]");
//            }
//        }
        // 通知青少儿版，老师这个时间段已被预约
//        RetInfo retInfo = notifyTeenAppointment(appointment.getTea_id(), appointment.getReserve_start_time(), appointment.getReserve_end_time(), Constants.AppointmentType.add);
//        if (retInfo != null && retInfo.getMark().equals("9002")) {
//            throw new ClientException("老师该时间已被预约[" + appointment.getReserve_start_time() + " - " + appointment.getReserve_end_time() + "]（青少儿版）");
//        }

        // 4. 插入预约信息
        appointment.setReserve_time(membSetmeal.getCou_time());//1节课的时长，单位为分钟
        appointment.setReserve_end_time(DateUtil.addMinute(appointment.getReserve_start_time(), membSetmeal.getCou_time()));//预约结束时间 =  预约开始时间 + 1节课的时长
        appointment.setState(Constants.ReserveState.ready_to_begin);//待上课
        appointment.setType(Constants.ReserveType.setmeal_course);//类型为购买课程预约
        appointment.setMemb_set_id(membSetmeal.getMemb_set_id());
        Date roomOpenTime = DateUtil.addMinute(appointment.getReserve_start_time(), -10);
        appointment.setRoom_open_time(roomOpenTime);
        Date roomCloseTime = DateUtil.addMinute(appointment.getReserve_end_time(), 10);
        appointment.setRoom_close_time(roomCloseTime);
        appointmentDao.insertSelective(appointment);
        /**
         * 判断是否是体验课，体验课则将优惠券置为不可用
         */
        if (appointment.getIs_trial()) {
            discountCouponDao.updateMembDiscountState(member.getMemb_id());
        }
       /* *
         * 插入一条系统消息
         */
        TdNtSystemMessage tdNtSystemMessage = new TdNtSystemMessage();
        tdNtSystemMessage.setSys_mes_type(2);
        tdNtSystemMessage.setUser_id(appointment.getTea_id());
        tdNtSystemMessage.setReserve_id(appointment.getReserve_id());
        tdNtSystemMessage.setSys_publish_time(new Timestamp(System.currentTimeMillis()));
        tdNtSystemMessageDao.insert(tdNtSystemMessage);

        // 5. 更新该套餐的可预约次数 set_reserve_size - 1
        appointmentDao.updateAppointmentSize(membSetmeal.getSet_reserve_size() - 1, membSetmeal.getMemb_set_id());

        // 6. 更新老师开通的时间段状态为已预约
        TeacherAppointmentTime teacherAppointmentTime = new TeacherAppointmentTime();
        teacherAppointmentTime.setTea_id(appointment.getTea_id());
        teacherAppointmentTime.setReserve_start_time(appointment.getReserve_start_time());
        teacherAppointmentTime.setReserve_end_time(appointment.getReserve_end_time());
        teacherAppointmentTime.setIs_valid(Constants.ReserveTimeState.booked);
        appointmentDao.updateAppointmentTimeStatus(teacherAppointmentTime);

        // 7. 创建教室
        ClassRoom classRoom = new ClassRoom();
        classRoom.setReserve_id(appointment.getReserve_id());
        classRoom.setTea_id(appointment.getTea_id());
        classRoom.setMemb_id(appointment.getMemb_id());
        classRoom.setCou_id(appointment.getCou_id());
        classRoom.setMemb_set_id(appointment.getMemb_set_id());
        classRoom.setRoom_state(Constants.RoomState.close);
        classRoom.setRoom_create_date(new Date());
        classRoom.setRoom_open_date(roomOpenTime);
        classRoom.setRoom_close_date(roomCloseTime);
        classRoomDao.insert(classRoom);

        // 8. 给教师发推送及邮件
        try {
            sendNotifyToTeacher(appointment, member);
        } catch (Exception e) {
            logger.error("邮件或推送发送失败", e);
        }

        // 9. 给学生发短信
        try {
            logger.info("发送短信 start\n 手机号：" + member.getMemb_phone_area() + "-" + member.getMemb_phone());
            Sms sms = new Sms(member.getMemb_phone(), member.getMemb_phone_area());
            Teacher t = teacherDao.getById(appointment.getTea_id());
            CourseInfo courseInfo = courseInfoDao.getById(appointment.getCou_id());
            String content = "【外教君】 您已成功预约";
            if (courseInfo != null) {
                content += "，课程名称：《" + courseInfo.getCou_name() + "》";
            }
            if (t != null) {
                content += "，上课老师：" + t.getTea_name();
            }
            String startTime = DateUtil.format(roomOpenTime, "yyyy-MM-dd HH:mm", appointment.getClientTimeZoneId());
            String endTime = DateUtil.format(roomCloseTime, "yyyy-MM-dd HH:mm", appointment.getClientTimeZoneId());
            content += "，教室开放时间：" + startTime + " 至 " + endTime;
            SMSUtil.sendSms(sms, content);
            logger.info("发送短信 end");
        } catch (Exception e) {
            logger.error("短信发送失败", e);
        }

        //10、返回课表
        List<ScheduleList> scheduleListList = new ArrayList<>();
        List<SystemConfig> systemConfigs = systemConfigDao.findByCode("systemAppointmentTimeThreshold");
        Map<String, Object> params = new HashMap<>();
        params.put("tea_id", appointment.getTea_id());
        int systemAppointmentTimeThreshold = Integer.parseInt(systemConfigs.get(0).getValue());
        logger.info("\n\n\nsystemAppointmentTimeThreshold=" + systemAppointmentTimeThreshold + "\n\n\n");

        // 第二步：查询老师7天内可以预约的时间
        //获取包括今天的7天的预约信息
        for (int i = 0; i < 7; i++) {
            ScheduleList scheduleList = new ScheduleList();
            Long date = System.currentTimeMillis();
            Date reserve_date = CommonUtil.addData(new Date(Long.valueOf(date)), i);
            params.put("reserve_date", reserve_date);
            params.put("time", systemAppointmentTimeThreshold);
            List<TdNtReserveTimeList> tdNtReserveTimeLists = appointmentDao.findTdNtReserveTimeList(params);
            List<TdNtReserveTimeList> tdNtReserveTimes = GetTeacherUtil.getReserveTime(reserve_date, clientTimeZone);
            for (TdNtReserveTimeList tdNtReserveTimeList : tdNtReserveTimeLists) {
                for (TdNtReserveTimeList tdNtReserveTimeList1 : tdNtReserveTimes) {
                    if (tdNtReserveTimeList.getDate().getTime() == tdNtReserveTimeList1.getDate().getTime()) {
                        tdNtReserveTimeList1.setIs_valid(tdNtReserveTimeList.getIs_valid());
                    }
                }
            }
            scheduleList.setSchedule_date(reserve_date);
            scheduleList.setSchedule_list(tdNtReserveTimes);
            scheduleListList.add(scheduleList);
        }
        return scheduleListList;
    }

    private RetInfo notifyTeenAppointment(Integer tea_id, Date reserve_start_time, Date reserve_end_time, Integer appointmentType) {
        Teacher teacher = teacherDao.getById(tea_id);
        RetInfo retInfo = RetInfo.getSuccessInfo();
        try {
            retInfo = HttpUtil.notifyTeenAppointment(teacher.getTea_email(), reserve_start_time, reserve_end_time, appointmentType);
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
        return retInfo;
    }

    private void sendNotifyToTeacher(Appointment appointment, TdNtMember member) {
        Teacher teacher = teacherDao.getById(appointment.getTea_id());
        if (teacher.getEqu_client_id() != null) {
            //  发推送
            try {
                String title = "NativeTalk";
                String body = "Dear NativeTalk tutor, new assignment class, please check the time for the class.\n ";
                logger.info("发推送 deviceType=" + teacher.getEqu_type() + ",  deviceId=" + teacher.getEqu_client_id());
                if (teacher.getEqu_type().equals(Constants.ClientOsType.android)) {
                    AndroidReserveTeacher.apnpush(title, body, teacher.getEqu_client_id(), appointment.getReserve_id());
                } else {
                    IosReserveTeacher.apnpush(title, body, teacher.getEqu_client_id(), appointment.getReserve_id());
                }
            } catch (Exception e) {
                logger.error("推送发送失败", e);
            }

            // 发邮件，freemarker 模板邮件
            try {
                BigDecimal tea_amount = new BigDecimal(websiteConfigDao.getData(24));//查询教学费用 老师每分钟0.2美分
                int courseDuration = appointment.getReserve_time();//预约的课程的上课时长
                BigDecimal earnMoney = tea_amount.multiply(new BigDecimal(courseDuration));//老师上完课应该赚取多少钱 = 每分钟单价 X 课程的时长（分钟）

                CourseInfo courseInfo = courseInfoDao.getById(appointment.getCou_id());// 查询课程信息

                // freemarker的model(数据模型)
                Map<String, Object> ftlModel = new HashedMap();
                ftlModel.put("tea_name", teacher.getTea_name());
                ftlModel.put("memb_name", member.getMemb_name());
                ftlModel.put("course_name", courseInfo.getCou_english_name());
                ftlModel.put("start_time", DateUtil.format(appointment.getReserve_start_time(), "MM-dd HH:mm"));
                ftlModel.put("money", earnMoney.doubleValue());

                // freemarker 初始化
                Configuration cfg = Configuration.getDefaultConfiguration();
                String path = this.getClass().getResource("/").getPath() + "email/";
                cfg.setDirectoryForTemplateLoading(new File(path));
                cfg.setDefaultEncoding("utf-8");
                Template temp = cfg.getTemplate("teacher_course_notify.ftl", "UTF-8");
                StringWriter stringWriter = new StringWriter();
                temp.process(ftlModel, stringWriter);

                String toEmail = teacher.getTea_email();//收件人邮箱
                String subject = "[NativeTalk] New Appointment";//邮件标题
                String htmlContent = stringWriter.toString();//邮件内容
                SendMailUtil.sendMail(toEmail, subject, htmlContent);// 发送邮件
            } catch (IOException e) {
                logger.error("邮件发送失败 email:" + teacher.getTea_email(), e);
            } catch (TemplateException e) {
                logger.error("邮件发送失败 email:" + teacher.getTea_email(), e);
            }

            // 发短信（如果老师有手机号就发送短信）
            if (StringUtils.isNotBlank(teacher.getTea_phone())) {
                Sms sms = new Sms(teacher.getTea_phone(), teacher.getTea_phone_area());
                boolean isSuccess = SMSUtil.sendSms(sms, "你有新的预约课，请在App中查看上课时间。预约详情已发送至邮箱：" + teacher.getTea_email());
                logger.info("预约-老师：给老师发送短信 - isSuccess:" + isSuccess);
            } else {
                logger.warn("预约-老师：上课前给老师发短信失败，无效的手机号:" + teacher.getTea_phone());
            }
        }
    }

    /**
     * 学生或老师进入教室
     *
     * @param request
     * @return
     */
    @Transactional
    public IntoClassRoomResponse intoClassRoom(IntoClassRoomRequest request, int userRole, int userId) {
        IntoClassRoomResponse response = new IntoClassRoomResponse();
        if (request.getRoomId() == null) {

            if (userRole == Constants.UserRole.student) {// 学生进入教室
                throw new ClientException("教室不存在，请联系客服");
            } else { // 老师进入教室
                throw new ClientException("Class does not exist, please contact customer service");
            }
        }
        ClassRoom room = classRoomDao.findById(request.getRoomId());
        if (room == null) {
            if (userRole == Constants.UserRole.student) {// 学生进入教室
                throw new ClientException("教室初始化失败");
            } else { // 老师进入教室
                throw new ClientException("Class initialization failed");
            }

        }

        // 1. 教室是否开放
        if (room.getRoom_state().intValue() == Constants.ClassRoom.RoomStatus.UN_START) {
            if (userRole == Constants.UserRole.student) {// 学生进入教室
                throw new ClientException("教室未开放");
            } else { // 老师进入教室
                throw new ClientException("Class is not open yet");
            }
        } else if (room.getRoom_state().intValue() == Constants.ClassRoom.RoomStatus.END) {
            if (userRole == Constants.UserRole.student) {// 学生进入教室
                throw new ClientException("教室已关闭");
            } else { // 老师进入教室
                throw new ClientException("Class is over");
            }
        } else if (room.getRoom_state().intValue() != Constants.ClassRoom.RoomStatus.OPEN) {
            if (userRole == Constants.UserRole.student) {// 学生进入教室
                throw new ClientException("教室已关门");
            } else { // 老师进入教室
                throw new ClientException("Class is closed");
            }
        }
        IntoClassRoom classRoom = IntoClassRoom.fromEntity(room);
        response.setRoom(classRoom);

        // 2. 查询课程和PPT信息
        CourseInfo courseInfo = courseInfoDao.getById(room.getCou_id());
        if (courseInfo == null) {
            logger.error("课程不存在，couId=" + room.getCou_id());
            if (userRole == Constants.UserRole.student) {// 学生进入教室
                throw new ClientException("课程不存在");
            } else { // 老师进入教室
                throw new ClientException("Course does not exist");
            }
        }
        // 3. 查询上次课学到哪张ppt
        MemberCourse memberCourse = memberCourseDao.findByStudentIdAndCouId(room.getMemb_id(), room.getCou_id());
        Integer lastStudyPage = 0;
        if (memberCourse != null) {
            lastStudyPage = memberCourse.getStudy_page() == null ? 0 : memberCourse.getStudy_page();
        }

        // 3. 查询课程目录（章节信息）
        List<CourseChapter> courseChapterList = courseInfoDao.findChapterByCouId(room.getCou_id());
        // 如果没有章节，设置一个默认章节，不然app会崩溃
        if (courseChapterList == null || courseChapterList.size() == 0) {
            CourseChapter chapter = new CourseChapter();
            chapter.setCou_id(room.getCou_id());
            chapter.setEnd_page(0);
            chapter.setStart_page(0);
            chapter.setLevel_english_name("Chapter 1");
            chapter.setLevel_sort(1);
            courseChapterList.add(chapter);
        }

        List<IntoClassRoomCoursePpt> pictures = coursePictureDao.findByCouId(room.getCou_id());// 课程的PPT
        IntoClassRoomCourseInfo intoClassRoomCourseInfo = IntoClassRoomCourseInfo.fromEntity(courseInfo, pictures);
        intoClassRoomCourseInfo.setLastPage(lastStudyPage); // 上堂课学到的最后一张ppt
        intoClassRoomCourseInfo.setCourseChapterList(courseChapterList);
        response.setCourseInfo(intoClassRoomCourseInfo);

        // 4. 查询老师信息
        Teacher teacher = teacherDao.getById(room.getTea_id());
        if (teacher == null) {
            logger.error("老师不存在，teacherId=" + room.getTea_id());
            if (userRole == Constants.UserRole.student) {// 学生进入教室
                throw new ClientException("老师不存在");
            } else { // 老师进入教室
                throw new ClientException("No teacher in the class");
            }
        }
        IntoClassRoomTeacher intoClassRoomTeacher = IntoClassRoomTeacher.fromEntity(teacher, room);
        intoClassRoomTeacher.setTeacher_agora_uid(agoraUidService.getAgoraUid(AgoraUid.Role.teacher, teacher.getTea_id()));
        response.setTeacher(intoClassRoomTeacher);

        // 5. 查询学生信息
        Student student = studentDao.getById(room.getMemb_id());
        if (student == null) {
            logger.error("学生不存在，memberId=" + room.getTea_id());
            if (userRole == Constants.UserRole.student) {// 学生进入教室
                throw new ClientException("学生不存在");
            } else {
                throw new ClientException("No student in the class");
            }
        }
        IntoClassRoomStudent intoClassRoomStudent = IntoClassRoomStudent.fromEntity(student, room);
        intoClassRoomStudent.setTeacher_agora_uid(agoraUidService.getAgoraUid(AgoraUid.Role.student, student.getMemb_id()));
        response.setStudent(intoClassRoomStudent);


        // 6. 验证请求api的用户是否是classRoom中记录的用户
        if (Constants.UserRole.student == userRole) {
            if (student.getMemb_id() != userId) {
                logger.error("学生进错教室了，membId=" + student.getMemb_id() + "，ClassRoom membId = " + userId);
                throw new ClientException("亲，您进错教室了！");
            }
        } else {
            if (teacher.getTea_id() != userId) {
                logger.error("老师进错教室了，teaId=" + teacher.getTea_id() + "，ClassRoom teaId = " + userId);
                throw new ClientException("Oops, wrong class!");
            }
        }

        // 7. 更新老师或学生进入教室的次数
        ClassRoomEntryLog entryLog = updateIntoClassRoomNumber(userRole, room, teacher, student);

        // 8. 记录进入教室日志（进出教室，网络状态，通话状态）
        entryLog.setEvent_date(new Date());
        entryLog.setRoom_id(room.getRoom_id());
        entryLog.setUser_role(userRole);
        entryLog.setEvent_type(Constants.ClassRoom.EventType.enter);
        entryLog.setCourse_type(Constants.CourseType._1v1);
        classRoomEntryLogDao.insert(entryLog);

        return response;
    }

    /**
     * 老师或学生离开教室
     *
     * @param request
     * @param userRole
     */
    public void leaveClassRoom(LeaveClassRoomRequest request, int userRole, int userId) {
        ClassRoom room = classRoomDao.findById(request.getRoomId());
        if (room == null) {
            if (userRole == Constants.UserRole.student) {// 学生进入教室
                throw new ClientException("教室初始化失败");
            } else { // 老师进入教室
                throw new ClientException("Class initialization failed");
            }
        }

        // 1. 查询老师信息
        Teacher teacher = teacherDao.getById(room.getTea_id());
        if (teacher == null) {
            logger.error("老师不存在，teacherId=" + room.getTea_id());
            if (userRole == Constants.UserRole.student) {// 学生进入教室
                throw new ClientException("老师不存在");
            } else { // 老师进入教室
                throw new ClientException("No Teacher in the class");
            }
        }

        // 2. 查询学生信息
        Student student = studentDao.getById(room.getMemb_id());
        if (student == null) {
            logger.error("学生不存在，memberId=" + room.getTea_id());
            if (userRole == Constants.UserRole.student) {// 学生进入教室
                throw new ClientException("学生不存在");
            } else { // 老师进入教室
                throw new ClientException("No student in the class");
            }
        }

        // 3. 更新老师或学生是否在教室里面
        if (userRole == Constants.UserRole.student) {
            // 学生离开教室
            room.setMemb_is_in_room(Constants.ClassRoom.InRoom.no);
        } else {
            // 老师离开教室
            room.setTea_is_in_room(Constants.ClassRoom.InRoom.no);
        }
        classRoomDao.update(room);

        // 3. 记录离开教室日志（进出教室，网络状态，通话状态）
        ClassRoomEntryLog entryLog = new ClassRoomEntryLog();
        entryLog.setEvent_date(new Date());
        entryLog.setRoom_id(room.getRoom_id());
        entryLog.setUser_role(userRole);
        entryLog.setUser_id(userId);
        entryLog.setEvent_type(Constants.ClassRoom.EventType.leave);
        entryLog.setLeave_reason(request.getReason());
        entryLog.setCourse_type(Constants.CourseType._1v1);
        classRoomEntryLogDao.insert(entryLog);
    }

    private ClassRoomEntryLog updateIntoClassRoomNumber(int userRole, ClassRoom room, Teacher teacher, Student student) {
        ClassRoomEntryLog entryLog = new ClassRoomEntryLog();
        if (userRole == Constants.UserRole.student) {
            // 学生进入教室
            room.setMemb_is_in_room(Constants.ClassRoom.InRoom.yes);
            room.setMemb_into_number(room.getMemb_into_number() + 1);
            entryLog.setUser_id(student.getMemb_id());
        } else {
            // 老师进入教室
            room.setTea_is_in_room(Constants.ClassRoom.InRoom.yes);
            room.setTea_into_number(room.getMemb_into_number() + 1);
            entryLog.setUser_id(teacher.getTea_id());
        }
        classRoomDao.update(room);
        return entryLog;
    }

    // 同步青少版版App预约时间到A版
    public void otherPlatformAppointment(OtherPlatformAppointmentDto dto) {
        try {
            Teacher teacher = teacherDao.findByEmail(dto.getTeaEmail());
            if (teacher == null) {
                throw new ClientException("无效的老师email:" + dto.getTeaEmail());
            }
            //预约时间内老师的开课情况
            List<ReserveTime> reserveTimeList = appointmentDao.findReserveTime(teacher.getTea_id(), dto.getAppointmentStartDate(), dto.getAppointmentEndDate());

            TeacherAppointmentTime teacherAppointmentTime = new TeacherAppointmentTime();
            teacherAppointmentTime.setTea_id(teacher.getTea_id());
            teacherAppointmentTime.setFrom_platform(Constants.AppointmentPlatform.T);//预约平台：T版
            teacherAppointmentTime.setReserve_start_time(dto.getAppointmentStartDate());
            teacherAppointmentTime.setReserve_end_time(dto.getAppointmentEndDate());
            if (Constants.AppointmentType.add.intValue() == dto.getAppointmentType().intValue()) {
                teacherAppointmentTime.setIs_valid(Constants.ReserveTimeState.booked);
                //比较的预约开始时间减了一分钟，为避免误差
                Date start_date_compare = new Date(dto.getAppointmentStartDate().getTime() - 1000 * 60);
                //预约的课程时长
                Long min = (dto.getAppointmentEndDate().getTime() - dto.getAppointmentStartDate().getTime()) / (1000 * 60);
                //占用时间块的数量
                Integer course_time = (int) Math.ceil((double) min / Integer.parseInt(cou_time));
                logger.info("reserveTimeList.size() = " + reserveTimeList.size() + "  ~~~~  course_time = " + course_time + " ~~~ compare " + (reserveTimeList.size() < course_time));
                // 预约列表为空
                if (reserveTimeList == null || reserveTimeList.size() == 0) {
                    //根据占用课时数添加对应预约数目
                    for (int i = 0; i < course_time; i++) {
                        teacherAppointmentTime.setDate(new Date(dto.getAppointmentStartDate().getTime() + 1000 * 60 * Integer.parseInt(cou_time) * i));
                        appointmentDao.addAppointmentTime(teacherAppointmentTime);
                    }
                    //预约课实际使用的时间块数量大于开课时间块数量
                } else if (reserveTimeList.size() < course_time) {
                    //第一个课时开启，第二个课时关闭（判断第一个课时有没有被预约，被预约抛出异常，没有被预约则修改第一课时状态，添加第二课时预约状态）
                    if (reserveTimeList.get(0).getIs_valid() == Constants.ReserveTimeState.booked) {
                        throw new ClientException("9002", "已被预约-->>" + JsonUtil.toJson(reserveTimeList.get(0).getDate()));
                    } else if (reserveTimeList.get(0).getDate().after(start_date_compare)) {
                        appointmentDao.updateAppointmentTimeStatus(teacherAppointmentTime);
                        teacherAppointmentTime.setDate(new Date(dto.getAppointmentStartDate().getTime() + 1000 * 60 * Integer.parseInt(cou_time)));
                        appointmentDao.addAppointmentTime(teacherAppointmentTime);
                    } else {
                        //第二个课时开启，第一个课时关闭（判断第二个课时有没有被预约，被预约抛出异常，没有被预约则修改第二课时状态，添加第一课时预约状态）
                        if (reserveTimeList.get(0).getIs_valid() == Constants.ReserveTimeState.booked) {
                            throw new ClientException("9002", "已被预约-->>" + JsonUtil.toJson(reserveTimeList.get(0).getDate()));
                        } else if (start_date_compare.before(reserveTimeList.get(0).getDate())) {
                            appointmentDao.updateAppointmentTimeStatus(teacherAppointmentTime);
                            teacherAppointmentTime.setDate(new Date(dto.getAppointmentStartDate().getTime() - 1000 * 60 * Integer.parseInt(cou_time)));
                            appointmentDao.addAppointmentTime(teacherAppointmentTime);
                        }
                    }
                    //预约课时数等于开课课时数
                } else if (reserveTimeList.size() == course_time) {
                    //判断所开课时有没有被预约，被预约则抛出异常
                    for (int i = 0; i < course_time; i++) {
                        if (reserveTimeList.get(i).getIs_valid().intValue() == Constants.ReserveTimeState.booked) {
                            throw new ClientException("9002", "已被预约-->>" + JsonUtil.toJson(reserveTimeList.get(i).getDate()));
                        }
                    }
                    //没有被预约，修改预约时间内的课时状态
                    teacherAppointmentTime.setReserve_start_time(dto.getAppointmentStartDate());
                    teacherAppointmentTime.setReserve_end_time(dto.getAppointmentEndDate());
                    teacherAppointmentTime.setIs_valid(Constants.ReserveTimeState.booked);
                    appointmentDao.updateAppointmentTimeStatus(teacherAppointmentTime);
                }
            } else {
                // 取消预约，修改预约时间内的可是状态，改为开启
                if (reserveTimeList != null) {
                    teacherAppointmentTime.setReserve_start_time(dto.getAppointmentStartDate());
                    teacherAppointmentTime.setReserve_end_time(dto.getAppointmentEndDate());
                    teacherAppointmentTime.setIs_valid(Constants.ReserveTimeState.open);
                    appointmentDao.updateAppointmentTimeStatus(teacherAppointmentTime);
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new ClientException("9999", "其他错误" + JsonUtil.toJson(e.getMessage()));
        }
    }

    public List<TeacherAppointmentTime> previewForA(AdminAppointmentPreviewRequest vo) {
        Teacher teacher = teacherDao.findByEmail(vo.getTea_email());
        if (teacher == null) {
            throw new RuntimeException("老师不存在，email=" + vo.getTea_email());
        }
        List<TeacherAppointmentTime> reserveTimeList = appointmentDao.appointmentPreview(teacher.getTea_id(), DateUtil.getFristTimeBlock(vo.getStart_date()));
        return reserveTimeList;
    }

    public ReserveTime appointmentSaveValidTimeBlockForA(AdminAppointmentSaveValidTimeBlockRequest vo) {
        Teacher teacher = teacherDao.findByEmail(vo.getTea_email());
        if (teacher != null) {
            ReserveTime rt = appointmentDao.findTimeBlock(teacher.getTea_id(), vo.getDate());
            return rt;
        } else {
            return null;
        }

    }

    // 青少版版后台预约同步时间状态到A版
    public void appointmentSaveForA(AdminApointmentSyncTimeBlockRequest vo) {
        Teacher teacher = teacherDao.findByEmail(vo.getTea_email());
        if (teacher != null) {
            List<TimeBlock> timeBlocks = vo.getTimeBlocks();
            for (TimeBlock tb : timeBlocks) {
                TeacherAppointmentTime teacherAppointmentTime = new TeacherAppointmentTime();
                teacherAppointmentTime.setTea_id(teacher.getTea_id());
                teacherAppointmentTime.setDate(tb.getDate());
                teacherAppointmentTime.setIs_valid(tb.getIs_valid());
                teacherAppointmentTime.setFrom_platform(tb.getPlatform());// 青少版后台预约

                ReserveTime rt = appointmentDao.findTimeBlock(teacher.getTea_id(), tb.getDate());
                if (rt != null) {
                    appointmentDao.updateTimeBlockStatus(teacherAppointmentTime);
                    logger.info("更新 - 预约时间块");
                } else {
                    appointmentDao.addAppointmentTime(teacherAppointmentTime);
                    logger.info("新增 - 预约时间块");
                }
            }
        }
    }
}
